package com.mf.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mf.dto.MACD.MACDDto;
import com.mf.entity.Code;
import com.mf.entity.RecommendCode;
import com.mf.entity.TapePurchaseHistory;
import com.mf.entity.WinRate;
import com.mf.service.*;
import com.mf.service.code.ICodeService;
import com.mf.utils.CCICalculator;
import com.mf.utils.CalculateKDJ;
import com.mf.utils.MACalculator;
import com.mf.utils.calculate.Calculate1;
import com.mf.utils.calculate.KdjCalculator;
import com.mf.vo.Calculate1Dto;
import com.mf.vo.MACD.MACDVo;
import com.mf.utils.Result;
import com.mf.vo.publicVo.DateScoped;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * ClassName: HomeController
 * Package: com.mf.controller
 * Description:
 *
 * @Author: lmf
 * @Create: 2024/4/30 16:49
 * @Version: 1.0
 */
@RestController
@RequestMapping("/stock/home")
@Tag(name = "首页")
public class HomeController {
    @Resource
    private IHomeService homeService;
    @Resource
    private IRecommendCodeService recommendCodeService;

    @Resource
    private ICodeService codeService;


    @Resource
    private IWinRateService winRateService;

    @Resource
    private IDealService dealService;
    @Resource
    private IStockPoolService stokePoolService;




    @PostMapping("/findMacd")
    @Operation(summary = "获取macd图形")
//    @RequestBody MACDDto macdDto
    public Result<MACDVo> findMacdByCode(@RequestBody MACDDto macdDto) {
        // 创建QueryWrapper对象来设置查询条件
        final LambdaQueryWrapper<RecommendCode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(RecommendCode::getD,"2018-04-30","2024-04-30");
        List<RecommendCode> codeList = recommendCodeService.list(queryWrapper);
        final MACDVo macdVo = setMacdVo(codeList);
        KdjCalculator.findIncreasingIndices2(macdVo);
//        KdjCalculator.findIncreasingIndices2(macdVo);
//        final WinRate winRate = Calculate1.findIncreasingIndices(macdVo, 5);
//        printWriter(winRate);
        return Result.success(macdVo);
//        return null;
    }

    @Operation(summary = "获取最新数据")
    @PostMapping("/findNewChart")
    public Result<MACDVo> findNewChart(@RequestBody DateScoped dateScoped) {
        List<RecommendCode> codesList =  codeService.findNewChart(dateScoped);
        final MACDVo macdVo = setMacdVo(codesList);
        getDateByScoped(dateScoped.getStart(), macdVo);
        return Result.success(macdVo);
    }

    /**
     * 获取时间范围内的数据
     */
    private void getDateByScoped(String date,MACDVo macdVo){
        int index = -1;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date target = sdf.parse(date);
            for(int i = 0; i < macdVo.getDate().length; i++){
                if(macdVo.getDate()[i] == null) {continue;} ;
                Date currentDate = sdf.parse(macdVo.getDate()[i]);
                if (currentDate.after(target)) {
                    index = i; // 返回第一个大于目标日期的字符串
                    break;
                }
            }
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        System.out.println(1);
        // 删除传入日期之前的数据
        if(index != -1){
            macdVo.setMacd(Arrays.copyOfRange(macdVo.getMacd(), index, macdVo.getMacd().length));
            macdVo.setK(Arrays.copyOfRange(macdVo.getK(), index, macdVo.getK().length));
            // 删除掉cci之前的数据
            macdVo.getCci().subList(0, index).clear();

            macdVo.setDate(Arrays.copyOfRange(macdVo.getDate(), index, macdVo.getDate().length));
            macdVo.setDea(Arrays.copyOfRange(macdVo.getDea(), index, macdVo.getDea().length));
            macdVo.setDif(Arrays.copyOfRange(macdVo.getDif(), index, macdVo.getDif().length));
            macdVo.getMa5().subList(0, index).clear();
            macdVo.getMa10().subList(0, index).clear();
            macdVo.getMa20().subList(0, index).clear();
            macdVo.getMa30().subList(0, index).clear();
            macdVo.getKdj().subList(0, index).clear();

        }
    }


    @Operation(summary = "随机获取100条股票代码并查询胜率")
    @GetMapping("/winMargin/{number}")
    public Result<WinRate> winMargin(@PathVariable("number") int number) throws ExecutionException, InterruptedException {
        final LambdaQueryWrapper<Code> codeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        codeLambdaQueryWrapper.notLike(Code::getDm,"ST");


        final List<Code> codeList = codeService.list(codeLambdaQueryWrapper);
        // 删除所有推荐和交易表使用新的数据
        dealService.remove(null);
        stokePoolService.remove(null);

        // 如果codeList中的元素少于100条，则使用所有元素
        int sizeToPick = Math.min(number, codeList.size());

        // 打乱
        Collections.shuffle(codeList);

        // 使用固定大小的线程池
        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        CountDownLatch latch = new CountDownLatch(sizeToPick); // 使用CountDownLatch等待所有任务完成

        System.out.println(latch.getCount()+"getCount");
        // 提交任务到线程池
        for (int i = 0; i < sizeToPick; i++) {
            final Code code = codeList.get(i);
            executor.submit(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    final MACDDto macdDto = new MACDDto();
                    macdDto.setDm(code.getDm());
                    macdDto.setType("dn");
                    final List<RecommendCode> historicalData = codeService.findHistoricalData(macdDto);
                    final MACDVo macdVo = setMacdVo(historicalData);
                    final Calculate1Dto calculate1Dto = Calculate1.findIncreasingIndices2(macdVo, 5);
                    dealService.saveBatch(calculate1Dto.getDealList());
                    stokePoolService.saveBatch(calculate1Dto.getStockPoolList());
                    System.out.println("=====================");
                    latch.countDown(); // 任务完成，计数减一

                    return null;
                }
            });
        }
        // 等待所有任务完成
        latch.await();
        System.out.println("完成======================");
        return Result.success(null);
    }

    public MACDVo setMacdVo(List<RecommendCode> codeList) {
        System.out.println(codeList);
        // 获取macd
        MACDVo macdVo =  homeService.findMacd(codeList);
        // 获取k线图
        double[][]  k =  homeService.getKLine(codeList);
        macdVo.setK(k);


        macdVo.setDm(codeList.get(0).getDm());

        final List<Double> ma5 = MACalculator.calculateMovingAverages(codeList, 5);
        final List<Double> ma10 = MACalculator.calculateMovingAverages(codeList, 10);
        final List<Double> ma20 = MACalculator.calculateMovingAverages(codeList, 20);
        final List<Double> ma30 = MACalculator.calculateMovingAverages(codeList, 30);
        macdVo.setMa5(ma5);
        macdVo.setMa10(ma10);
        macdVo.setMa20(ma20);
        macdVo.setMa30(ma30);

        // 设置kdj指标
        macdVo.setKdj(CalculateKDJ.getKDJ(macdVo));
        // 获取cci
        final List<Double> cciList = CCICalculator.calculateCCI(codeList, 14);
        macdVo.setCci(cciList);
        return  macdVo;
    }

}
